﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BA2009.Entities;
using BA2009.DataAccess;
using System.Configuration;
using BA2009.DataAccess.Context;
using System.Runtime.Remoting;
using System.Data.Linq;
using System.Transactions;

namespace BA2009.Data.DataAccess
{
    public abstract class RepositoryBase<T> :IRepository<T>
        where T:EntityBase
    {

        protected BA2009Context db;

        public RepositoryBase()
        {
            db = new BA2009Context(BA2009.Context.Constants.CONNECTION_STRING);
        }

        #region IRepository<T> Members

        public abstract IQueryable<T> FindAll();

        public abstract T GetById(int id);

        public int Add(T item, params object[] maps)
        {
            using (var tran = new TransactionScope())
            {
                try
                {


                    ObjectHandle entityWrap = Activator.CreateInstance(BA2009.Context.Constants.DATA_ASSEMBLY, item.GetLinqTypeName());

                    var linqEntity = entityWrap.Unwrap();
                    //Activator
                    //var test = (BA2009.DataAccess.Entities.Page)linqEntity;
                    item.SetLinqProperties(ref linqEntity);

                    using (var db = new BA2009Context(BA2009.Context.Constants.CONNECTION_STRING))
                    {
                      
                            this.Save(linqEntity, db,maps);

                            //Complete the transaction
                            tran.Complete();
                       
                    }

                    return Convert.ToInt32(BA2009.Utility.Reflection.GetObjectValue(string.Concat(item.TableName, "ID"), linqEntity));

                }
                catch (Exception ex)
                {
                    Utility.ExceptionManager.Handle(ex);
                    tran.Dispose();
                    return 0;
                }
            }
        }

        public bool Delete(T item)
        {
            using (var tran = new TransactionScope())
            {
                try
                {
                    using (var db = new BA2009Context(BA2009.Context.Constants.CONNECTION_STRING))
                    {

                        this.Delete(item.GetPKValue(), db);
                        tran.Complete();

                    }

                    return true;
                }
                catch (Exception ex)
                {
                    Utility.ExceptionManager.Handle(ex);
                    tran.Dispose();
                    return false;
                }
            }
        }

        public int Update(T item, params object[] maps)
        {
            using (var tran = new TransactionScope())
            {
                try
                {

                    ObjectHandle entityWrap = Activator.CreateInstance(BA2009.Context.Constants.DATA_ASSEMBLY, item.GetLinqTypeName());

                    var linqEntity = entityWrap.Unwrap();
                    item.SetLinqProperties(ref linqEntity);

                    var original = this.GetLinqEntity(item.GetPKValue());
                    using (var db = new BA2009Context(BA2009.Context.Constants.CONNECTION_STRING))
                    {

                        this.Update(linqEntity, original, db,maps);
                        tran.Complete();

                    }

                    

                    return Convert.ToInt32(BA2009.Utility.Reflection.GetObjectValue(string.Concat(item.TableName, "ID"), linqEntity));


                }
                catch (Exception ex)
                {
                    Utility.ExceptionManager.Handle(ex);
                    tran.Dispose();
                    return 0;
                }
            }
        }
       

        #endregion

        #region Protected methods


        protected abstract void Save(object linqEnity, BA2009Context dbContext, params object[] maps);

        protected abstract void Delete(int id, BA2009Context dbContext);

        protected abstract void Update(object itemToUpdate, object orginialItem, BA2009Context dbContext, params object[] maps);

        protected abstract object GetLinqEntity(int id);

        #endregion
    }
}
